package com.example.origin.redis.utils;

import com.github.luben.zstd.Zstd;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

@Slf4j
public class ZstdBufferedRedisSerializer<T> implements RedisSerializer<T> {

    private final RedisSerializer<T> originSerializer;
    private final int limit;

    public ZstdBufferedRedisSerializer(RedisSerializer<T> originSerializer, int limit) {
        this.originSerializer = originSerializer;
        this.limit = limit;
    }

    public ZstdBufferedRedisSerializer(RedisSerializer<T> originSerializer) {
        this(originSerializer, 1000_000);
    }

    private byte[] zstdEncode(byte[] input) {
        return Zstd.compress(input);
    }

    private byte[] zstdDecode(byte[] input, int size) {
        return Zstd.decompress(input, size);
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        final byte[] bytes = originSerializer.serialize(t);
        if (bytes == null) {
            return null;
        }
        if (bytes.length > limit) {
            return zstdEncode(bytes);
        }
        return bytes;
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null) {
            return null;
        }
        try {
            final long size = Zstd.decompressedSize(bytes);
            if (size > 0) {
                bytes = zstdDecode(bytes, (int) size);
            }
        } catch (Exception e) {
            log.error("error getting size", e);
            throw e;
        }
        return originSerializer.deserialize(bytes);
    }
}
